package com.adcc.ags.cgw.service;

import com.adcc.ags.cgw.configuration.UserListFactory;
import com.adcc.ags.cgw.entity.msg.CGWMsg;
import com.adcc.ags.cgw.entity.msg.DestRoute;
import com.adcc.ags.cgw.entity.msg.MsgType;
import com.adcc.ags.cgw.entity.msg.TrafficMsg;
import com.adcc.ags.cgw.entity.user.*;
import com.adcc.ags.cgw.proxy.MsgProxy;
import com.adcc.ags.cgw.utils.Constant;
import com.adcc.utility.log.Log;
import com.adcc.utility.msg620.ACARS620Msg;
import com.adcc.utility.msg620.ACARS620Parser;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;

import java.util.*;
import java.util.regex.Pattern;

/**
 * 消息路由服务接口实现类
 */
public class MsgRouterServiceImpl extends MsgRouterService {

    /**
     * 将路由规则转化为正则表达式
     * @param route
     * @return
     */
    private String formatRouteToRegex(String... route){
        String strRegex = Strings.nullToEmpty("");
        if(route != null && route.length > 0){
            for(int i=0; i< route.length; i++){
                if(i == route.length -1){
                    strRegex += route[i].replace(Constant.CHAR_USER_ROUTE,Constant.CHAR_USER_REGEX);
                }else{
                    strRegex += route[i].replace(Constant.CHAR_USER_ROUTE,Constant.CHAR_USER_REGEX) + "|";
                }
            }
        }
        return strRegex;
    }

    /**
     * 查找用户ID
     * @param dest
     * @return
     */
    private String findUserId(String dest){
        String strUsers = Strings.nullToEmpty("");
        for(User user : UserListFactory.getInstance().getUserList()){
            if(dest.equals(user.getRecvQueue())){
                strUsers =  user.getId();
                break;
            }
        }
        return strUsers;
    }

    @Override
    protected boolean matchRoute(String element, String... route) {
        try {
            String strRegex = formatRouteToRegex(route);
            return Pattern.matches(strRegex,element);
        } catch (Exception ex) {
            Log.error(MsgRouterService.class.getName(), "matchRoute() error", ex);
            return false;
        }
    }

    @Override
    protected boolean matchRoute(String[] element, String... route) {
        try {
            String strRegex = formatRouteToRegex(route);
            for(String elt : element){
                if(Pattern.matches(strRegex,elt)){
                    return true;
                }
            }
            return false;
        } catch (Exception ex) {
            Log.error(MsgRouterService.class.getName(), "matchRoute() error", ex);
            return false;
        }
    }

    @Override
    protected boolean matchRoute(String element, int start, String route) {
        try {
            String strRegex = formatRouteToRegex(route);
            return Pattern.compile(strRegex).matcher(element).find(start);
        } catch (Exception ex) {
            Log.error(MsgRouterService.class.getName(), "matchRoute() error", ex);
            return false;
        }
    }

    @Override
    protected List<DestRoute> findDownlinkRoute(CGWMsg msg) {
        try{
            List<DestRoute> destList = Lists.newArrayListWithExpectedSize(500);
            List<User> userList = UserListFactory.getInstance().getUserList();
            for(User user : userList){

                // 如果用户配置为全部转发，则下行报文不匹配路由直接发送
                if(user.isDownlinkForward()){
                    destList.add(new DestRoute(user.getId(),user.getRecvQueue()));
                }else{
                    if(user.getRouteList().size() > 0){
                        byte[] buffer = msg.getMsg().getContent();
                        Optional<ACARS620Msg> optional = ACARS620Parser.parse(new String(buffer, 0, buffer.length));
                        if(optional.isPresent()){
                            for(Route route : user.getRouteList()){
                                if(route.getType() == RouteType.Downlink){
                                    boolean flag = true;
                                    DownlinkRoute dr = (DownlinkRoute)route;

                                    // 匹配接收地址
                                    if(dr.getRecvAddress() != null && dr.getRecvAddress().length > 0){
                                        flag = matchRoute(optional.get().getRecvAddress(),dr.getRecvAddress());
                                    }

                                    // 匹配发送地址
                                    if(!Strings.isNullOrEmpty(dr.getSendAddress())){
                                        flag = flag & matchRoute(optional.get().getSendAddress(),dr.getSendAddress());
                                    }

                                    // 匹配报文类型
                                    if(dr.getSmi() != null && dr.getSmi().length > 0){
                                        flag = flag & matchRoute(optional.get().getSmi(),dr.getSmi());
                                    }

                                    // 匹配航班号
                                    if(dr.getFi() != null && dr.getFi().length > 0){
                                        flag = flag & matchRoute(optional.get().getFi(),dr.getFi());
                                    }

                                    // 匹配机尾号
                                    if(dr.getAn() != null && dr.getAn().length > 0){
                                        flag = flag & matchRoute(optional.get().getAn(),dr.getAn());
                                    }

                                    // 匹配RGS站
                                    if(dr.getRgs() != null && dr.getRgs().length > 0){
                                        flag = flag & matchRoute(optional.get().getRgs(),dr.getRgs());

                                    }

                                    // 匹配关键字
                                    if(dr.getSpecLabel() != null && !Strings.isNullOrEmpty(dr.getSpecLabel().getContent()) && dr.getSpecLabel().getIndex() >=0) {
                                        flag = flag & matchRoute(optional.get().getFreeText(), dr.getSpecLabel().getIndex(), dr.getSpecLabel().getContent());
                                    }
                                    if(flag){
                                        destList.add(new DestRoute(user.getId(),user.getRecvQueue()));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return destList;
        }catch (Exception ex){
            Log.error(MsgRouterService.class.getName(), "findDownlinkRoute() error",ex);
            return null;
        }
    }

    @Override
    protected List<DestRoute> findUplinkRoute(CGWMsg msg) {
        try{
            List<DestRoute> destList = Lists.newArrayListWithExpectedSize(5);
            User user = msg.getUser().get();
            if(user!= null && user.getRouteList().size() > 0){
                byte[] buffer = msg.getMsg().getContent();
                Optional<ACARS620Msg> optional = ACARS620Parser.parse(new String(buffer, 0, buffer.length));
                if (optional.isPresent()) {
                    for(Route route : user.getRouteList()){
                        if(route.getType() == RouteType.Uplink){
                            boolean flag = true;
                            UplinkRoute ur = (UplinkRoute)route;

                            // 匹配接收地址
                            if(ur.getRecvAddress() != null && ur.getRecvAddress().length > 0){
                                flag = matchRoute(optional.get().getRecvAddress(),ur.getRecvAddress());
                            }

                            // 匹配发送地址
                            if(!Strings.isNullOrEmpty(ur.getSendAddress())){
                                flag = flag & matchRoute(optional.get().getSendAddress(),ur.getSendAddress());
                            }

                            // 匹配报文类型
                            if(ur.getSmi() != null && ur.getSmi().length > 0){
                                flag = flag & matchRoute(optional.get().getSmi(),ur.getSmi());
                            }

                            // 匹配机尾号
                            if(ur.getAn() != null && ur.getAn().length > 0){
                                flag = flag & matchRoute(optional.get().getAn(),ur.getAn());
                            }

                            // 匹配关键字
                            if(ur.getSpecLabel() != null && !Strings.isNullOrEmpty(ur.getSpecLabel().getContent()) && ur.getSpecLabel().getIndex() >=0) {
                                flag = flag & matchRoute(optional.get().getFreeText(), ur.getSpecLabel().getIndex(), ur.getSpecLabel().getContent());
                            }
                            if(flag){
                                if(ur.getDestination() != null && ur.getDestination().length > 0){
                                    for(String strDest : ur.getDestination()){
                                        String userId = findUserId(strDest);
                                        if(!Strings.isNullOrEmpty(userId)){
                                            destList.add(new DestRoute(userId,strDest));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return destList;
        } catch (Exception ex) {
            Log.error(MsgRouterService.class.getName(), "findUplinkRoute() error",ex);
            return null;
        }
    }

    @Override
    protected List<DestRoute> findGroundRoute(CGWMsg msg) {
        try {
            List<DestRoute> destList = Lists.newArrayListWithExpectedSize(5);
            User user = msg.getUser().get();
            if(user!= null && user.getRouteList().size() > 0) {
                byte[] buffer = msg.getMsg().getContent();
                String strMsg = new String(buffer, 0, buffer.length);
                for(Route route : user.getRouteList()) {
                    if(route.getType() == RouteType.Ground) {
                        boolean flag = true;
                        GroundRoute gr = (GroundRoute) route;

                        // 匹配关键字
                        if(gr.getSpecLabel() != null && !Strings.isNullOrEmpty(gr.getSpecLabel().getContent()) && gr.getSpecLabel().getIndex() >=0) {
                            flag = matchRoute(strMsg, gr.getSpecLabel().getIndex(), gr.getSpecLabel().getContent());
                        }
                        if(flag) {
                            if (gr.getDestination() != null && gr.getDestination().length > 0) {
                                for (String strDest : gr.getDestination()) {
                                    String strUserId = findUserId(strDest);
                                    if(!Strings.isNullOrEmpty(strUserId)){
                                        destList.add(new DestRoute(strUserId,strDest));
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return destList;
        } catch (Exception ex) {
            Log.error(MsgRouterService.class.getName(), "findGroundRoute() error", ex);
            return null;
        }
    }

    @Override
    public void onReceive(Object message) {
        super.onReceive(message);
        try{

            CGWMsg cgwMsg = (CGWMsg)message;
            if(cgwMsg != null){
                Log.debug(MsgSenderService.class.getName(),"MsgRouter receive message\r\n" + cgwMsg.getMsg().toString());
                if(cgwMsg.getType() == MsgType.DOWNLINK){

                    // 查找下行路由
                    List<DestRoute> destList = findDownlinkRoute(cgwMsg);

                    // 根据下行路由向用户分发下行报文
                    if(destList != null && destList.size() > 0){
                        cgwMsg.setDestination(destList);
                        for(DestRoute dr : destList){
                            CGWMsg cm = new CGWMsg(cgwMsg.getMsg(),cgwMsg.getType(),cgwMsg.getSender());
                            cm.getDestination().add(dr);
                            MsgProxy.getInstance().getMsgSendActor().tell(cm, this.getSelf());
                        }
                        Log.debug(MsgRouterService.class.getName(), "dispatch downlink message to" + cgwMsg.getReceiver());
                    }else {
                        Log.debug(MsgRouterService.class.getName(), "downlink message not find destination user\r\n" + cgwMsg.getMsg().toString());
                    }

                    // MsgStore更新接收用户
                    cgwMsg.setReceiver(cgwMsg.getChangedReceiver().get());
                    MsgProxy.getInstance().getMsgSaveActor().tell(new TrafficMsg(cgwMsg), this.getSelf());
                }else{

                    // 上行和地地报文路由处理
                    if (MsgType.UPLINK == cgwMsg.getType()) {

                        // 查找上行路由
                        cgwMsg.setDestination(findUplinkRoute(cgwMsg));

                        // MsgStore更新接收用户
                        Optional<String> optional = cgwMsg.getChangedReceiver();
                        if(optional.isPresent()){
                            cgwMsg.setReceiver(optional.get());
                            MsgProxy.getInstance().getMsgSaveActor().tell(new TrafficMsg(cgwMsg.getId(),cgwMsg.getReceiver()),this.getSelf());
                        }

                        // 根据上行路由向用户分发上行报文
                        MsgProxy.getInstance().getMsgSendActor().tell(cgwMsg, this.getSelf());
                        Log.debug(MsgRouterService.class.getName(), "dispatch uplink message to" + cgwMsg.getReceiver());
                    } else if (MsgType.GROUND == cgwMsg.getType()) {

                        // 查找地地路由
                        List<DestRoute> destList = findGroundRoute(cgwMsg);

                        // 根据地地路由向用户分发地地报文
                        if (destList != null && destList.size() > 0) {
                            cgwMsg.setDestination(destList);

                            // MsgStore更新接收用户
                            Optional<String> optional = cgwMsg.getChangedReceiver();
                            if(optional.isPresent()){
                                cgwMsg.setReceiver(optional.get());
                                MsgProxy.getInstance().getMsgSaveActor().tell(new TrafficMsg(cgwMsg.getId(),cgwMsg.getReceiver()),this.getSelf());
                            }
                            MsgProxy.getInstance().getMsgSendActor().tell(cgwMsg, this.getSelf());
                            Log.debug(MsgRouterService.class.getName(), "dispatch ground message to" + cgwMsg.getReceiver());
                        }else {
                            Log.debug(MsgRouterService.class.getName(), "ground message not find destination user\r\n" + cgwMsg.getMsg().toString());
                        }
                    }
                }
            }else {
                Log.error(MsgRouterService.class.getName(),"receive invalid message");
                unhandled(message);
            }
        }catch (Exception ex){
            Log.error(MsgRouterService.class.getName(),"onReceive() error",ex);
        }
    }
}
